package study.JavaAdvanced;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * date：2025.10.29
 * author：fzy
 * title：java多线程
 */
//一条线程指的是进程中单一顺序的控制流
//一个进程可以并行多个线程，每条线程执行不同的人物
//线程的生命周期
//新建状态->strat->就绪->run()->运行(-->阻塞:让出cpu资源)->stop->死亡
//详细说一下：
//1.新建状态：初始化一个thread类后就处于新建状态，他将保持这个状态直到strat()
//2.就绪态：使用了start()后，该线程就处于就绪态，等待JVM调度
//3.运行态：可变为阻塞，就绪，死亡状态
//4.阻塞状态：如果一个线程执行了sleep()-睡眠、suspend()-挂起,失去占用资源后，该线程就从就绪态变为阻塞状态，在睡眠时间到了重新获取资源可以重新进入就绪状态分为三种
//4.1 等待阻塞 运行态线程执行wait()方法，使线程进入等待阻塞状态
//4.2 同步阻塞 线程在获取synchronized同步锁失败(因为同步锁被其他线程占用)---这是？
//4.3 其他阻塞 调用sleep()和join()发出了IO请求时，线程就会进入阻塞状态，sleep()状态超时的时候，join等待线程终止或者超市，io获取完毕，线程重新进入就绪态
//5.死亡状态：一个运行的线程完成任务或被其他条件终止，线程就进入死亡状态
//优先级
//每个线程都有优先级，取值范围1-10，默认5
//优先级高的先用内存，但是优先级不能保证顺序，非常依赖平台---？
public class Java_8 {
    public static void main(String[] arg) {
//        ThreadTestClass.RunnableTest();
//        ThreadTestClass.ThreadTest();
        ThreadTestClass.callAbleTest();
    }
}

class ThreadTestClass {
    static void RunnableTest() {
        //这里创建了两个线程，线程一每次睡眠时间是1s，线程2是3s
        RunnableClass runnableClass = new RunnableClass("Thread_One", 1000);
        RunnableClass runnableClass_copy = new RunnableClass("Thread_Two", 3000);
        runnableClass.start();
        runnableClass_copy.start();
    }

    static void ThreadTest() {
        ThreadClass threadClass = new ThreadClass("Thread_one", ThreadType.THREAD_TYPE_ONE);
        ThreadClass threadClass1 = new ThreadClass("Thread_two", ThreadType.THREAD_TYPE_TWO);
        System.out.println("当前线程： " + threadClass.getName());
        threadClass.setName("Thread_one");
        //线程改名
        System.out.println("当前线程： " + threadClass.getName());
        //设置线程优先级
        threadClass.setPriority(6);
        //中断线程
//        threadClass.interrupt();
        //线程是否活动
        threadClass.isAlive();
        threadClass.start();
        threadClass1.start();
    }

    //通过callable和feature创建线程
//实现CallAble的类，实现call方法，该方法作为线程的执行体，
//创建CallAble实例，并且利用FutureTask来包装这个类
//使用Future作为Thread对象的target来创建启动线程
//调用FutureTask的get方法获取子线程结束后的返回值
    //callable产生结果，future获取结果
    //runnable和Thread无法在运行之后立即获取结果，因为是重写的run方法
    static void callAbleTest() {
        CallAbleClass callAbleClass = new CallAbleClass();
        FutureTask<Integer> fts = new FutureTask<>(callAbleClass);
        new Thread(fts, "有返回值的线程").start();
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + " 的循环变量值 " + i);

            try {
                System.out.println(fts.get());
            } catch (ExecutionException e) {
                throw new RuntimeException(e);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

    }
}

//线程创建
//1.实现Runnable接口
//2.继承Thread本身
//3.通过Callable和future创建线程


//1.实现Runnable接口
//1.1重写run方法，实现Runnable类:run方法可能是线程的入口方法
//1.2实例化Runnable实现类，使用thread类新建一个线程类
//1.3调用线程的start方法进行运行
class RunnableClass implements Runnable {
    private Thread threadOb;
    private String name;
    int sleepValue;

    RunnableClass(String name, int sleepValue) {
        this.name = name;
        this.sleepValue = sleepValue;
    }

    @Override
    public void run() {
        System.out.println("Running: " + name);
        try {
            int i = 0;
            do {
                System.out.println("Thread: " + name + "   " + i);
                //这里让这个线程睡眠1秒
                Thread.sleep(sleepValue);
                //Q:Thread.sleep是个静态方法，不依赖类，JVM运行的时候怎么区分是哪个线程调用的这个方法
                //A(来自豆包AI):Thread.sleep虽然是静态方法，但是作用对象是当前正在执行的栈的线程，也就是哪个线程执行的这个sleep方法让谁睡眠5秒, 多个线程之间互不干扰，这个说法很透彻了
                i++;
            } while (i < 4);

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Exiting: " + name);
    }

    public void start() {
        System.out.println("Start: " + name);
        if (threadOb == null) {
            //注意这里：将这个类使用构造方法创建线程之后，实现的run方法就是线程的入口方法
            threadOb = new Thread(this, name);//这里有点抽象
            System.out.println("Create: " + name);
            threadOb.start();
        }
    }
}

//2 通过继承Thread来实现多线程
//依旧必须重写run方法，该方法是线程的入口
enum ThreadType {
    THREAD_TYPE_ONE, THREAD_TYPE_TWO;
}

class ThreadClass extends Thread {
    private ThreadType type;
    private Thread thread;
    private String name;
    final int breakValue = 2;

    ThreadClass(String name, ThreadType type) {
        this.name = name;
        this.type = type;
    }

    @Override
    public void run() {
        System.out.println("Run: " + name);
        switch (type) {
            case ThreadType.THREAD_TYPE_ONE:
                dealFun_one();
                break;
            case ThreadType.THREAD_TYPE_TWO:
                dealFun_two();
                break;
        }
    }

    public void start() {
        if (thread == null) {
            thread = new Thread(this, name);
            thread.start();
            System.out.println("Create: " + name);
        }
    }

    public void dealFun_one() {
        try {
            System.out.println("开始处理请求 当前breakValue: " + breakValue + "-----" + name);

            for (int i = 0; i < 5; i++) {
                System.out.println("当前请求：" + name + "  " + i);
                if (i == 2) {
                    break;
                }
                Thread.sleep(1000);
            }
            System.out.println("请求处理完成: " + name);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void dealFun_two() {
        System.out.println("你好");
    }
}


class CallAbleClass implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        int i = 0;
        for (; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + " " + i);
        }
        return i;
    }
}